package com.dragon.user_service.util;


import cn.hutool.json.JSONUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;
import com.dragon.user_service.domain.entity.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.Map;
import java.util.Optional;

@Slf4j
@Component
public class JwtUtils {

    /**
     * token秘钥，请勿泄露，请勿随便修改
     */
    @Value("${jwt.secret}")
    private String secret;

    private static final String UID_CLAIM = "uid";

    private static final String USER_CLAIM = "user";
    private static final String CREATE_TIME = "createTime";

    private static final long EXPIRATION_TIME = 5 * 24 * 60 * 60 * 1000L; // 注意 L 表示 long 类型

    /**
     * JWT生成Token.<br/>
     * <p>
     * JWT构成: header, payload, signature
     */
    public String createToken(Long uid) {
        // build token
        String token = JWT.create()
                .withClaim(UID_CLAIM, uid) // 只存一个uid信息，其他的自己去redis查
                .withClaim(CREATE_TIME, new Date(System.currentTimeMillis()))
                .withExpiresAt(new Date(System.currentTimeMillis()+EXPIRATION_TIME))
                .sign(Algorithm.HMAC256(secret)); // signature
        return token;
    }
    public String createToken(User user) {
        String userStr = JSONUtil.toJsonStr(user);
        // build token
        String token = JWT.create()
                .withClaim(USER_CLAIM, userStr) // 只存一个uid信息，其他的自己去redis查
                .withClaim(CREATE_TIME, new Date(System.currentTimeMillis()))
                .withExpiresAt(new Date(System.currentTimeMillis()+EXPIRATION_TIME))
                .sign(Algorithm.HMAC256(secret)); // signature
        return token;
    }
/*
张三:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
eyJjcmVhdGVUaW1lIjoxNzUwMzQwMjc0LCJleHAiOjE3NTA3NzIyNzQsInVzZXIiOiJ7XCJ1c2VyX2lkXCI6MTkzNTYyOTE1NDM1MTkzMTM5NCxcInVzZXJOYW1lXCI6XCLlvKDkuIlcIixcInVzZXJQYXNzd29yZFwiOlwiMGUxMGUwYjlhMGE4MzA1ZmIyYmU1MWQyMGRkZGQ0ZjRcIixcInVzZXJSb2xlXCI6XCJ1c2VyXCIsXCJpc0RlbGV0ZVwiOjAsXCJlZGl0VGltZVwiOjE3NTAzNTM3MjcwMDAsXCJjcmVhdGVUaW1lXCI6MTc1MDM1MzcyNzAwMCxcInVwZGF0ZVRpbWVcIjoxNzUwMzUzNzI3MDAwfSJ9.
zRWJosIY5YocnmqKkFVzL0k4AMng-nqsc4eOWDpYkxg
 */
/*
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
eyJjcmVhdGVUaW1lIjoxNzUwNDA3OTQ1LCJleHAiOjE3NTA4Mzk5NDUsInVzZXIiOiJ7XCJ1c2VyX2lkXCI6MTkzNTY5OTI5OTYwMjU2NzE3MCxcInVzZXJOYW1lXCI6XCLmnY7lm5tcIixcInVzZXJQYXNzd29yZFwiOlwiNGE4NmZmZTg4YWYxYTMwNmIxOTI4NDdhMThmYTRlZmFcIixcInVzZXJSb2xlXCI6XCJ1c2VyXCIsXCJpc0RlbGV0ZVwiOjAsXCJlZGl0VGltZVwiOjE3NTAzNzA0NTEwMDAsXCJjcmVhdGVUaW1lXCI6MTc1MDM3MDQ1MTAwMCxcInVwZGF0ZVRpbWVcIjoxNzUwMzcwNDUxMDAwfSJ9.
pMr1Flv_lMpy-6QWmzVzgBD6TWkPd4p6s_PjbhSlhYA
 */
/*
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
eyJjcmVhdGVUaW1lIjoxNzUwMzQwMjc0LCJleHAiOjE3NTA3NzIyNzQsInVzZXIiOiJ7XCJ1c2VyX2lkXCI6MTkzNTYyOTE1NDM1MTkzMTM5NCxcInVzZXJOYW1lXCI6XCLlvKDkuIlcIixcInVzZXJQYXNzd29yZFwiOlwiMGUxMGUwYjlhMGE4MzA1ZmIyYmU1MWQyMGRkZGQ0ZjRcIixcInVzZXJSb2xlXCI6XCJ1c2VyXCIsXCJpc0RlbGV0ZVwiOjAsXCJlZGl0VGltZVwiOjE3NTAzNTM3MjcwMDAsXCJjcmVhdGVUaW1lXCI6MTc1MDM1MzcyNzAwMCxcInVwZGF0ZVRpbWVcIjoxNzUwMzUzNzI3MDAwfSJ9.
zRWJosIY5YocnmqKkFVzL0k4AMng-nqsc4eOWDpYkxg
 */





    /**
     * 解密Token
     *
     * @param token
     * @return
     */


    public Map<String, Claim> verifyToken(String token) {
        if (StringUtils.isEmpty(token)) {
            return null;
        }
        try {
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secret)).build();
            DecodedJWT jwt = verifier.verify(token);
            return jwt.getClaims();
        } catch (Exception e) {
            log.error("decode error,token:{}", token, e);
        }
        return null;
    }


    /**
     * 根据Token获取uid
     *
     * @param token
     * @return uid
     */
    public Long getUidOrNull(String token) {
        return Optional.ofNullable(verifyToken(token))
                .map(map -> map.get(UID_CLAIM))
                .map(Claim::asLong)
                .orElse(null);
    }
    public User getUserOrNull(String token) {

        String userStr = Optional.ofNullable(verifyToken(token))
                .map(map -> map.get(USER_CLAIM))
                .map(Claim::asString)
                .orElse(null);
        User userBean = JSONUtil.toBean(userStr, User.class);
        return userBean;
    }

}